package handler

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/olivere/elastic/v7"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"shop/goods-srv/global"
	"shop/goods-srv/model"
	"shop/goods-srv/proto"
)

type GoodsService struct {
}

func GoodsModelToResponse(goods model.Goods) proto.GoodsInfoResponse {
	var goodsInfoResponse = proto.GoodsInfoResponse{

		Id:              goods.ID,
		CategoryId:      goods.CategoryId,
		Name:            goods.Name,
		GoodsSn:         goods.GoodsSn,
		ClickNum:        goods.ClickNum,
		SoldNum:         goods.SoldNum,
		FavNum:          goods.FavNum,
		MarketPrice:     goods.MarketPrice,
		ShopPrice:       goods.ShopPrice,
		GoodsBrief:      goods.GoodsBrief,
		ShipFree:        goods.ShipFree,
		GoodsFrontImage: goods.GoodsFrontImage,
		IsNew:           goods.IsNew,
		IsHot:           goods.IsHot,
		OnSale:          goods.OnSale,
		DescImages:      goods.DescImages,
		Images:          goods.Images,
		Category: &proto.CategoryBriefInfoResponse{
			Id:   goods.CategoryId,
			Name: goods.Category.Name,
		},
		Brand: &proto.BrandInfoResponse{
			Id:   goods.Brands.ID,
			Name: goods.Brands.Name,
			Logo: goods.Brands.Logo,
		},
	}
	return goodsInfoResponse
}

func (g *GoodsService) GoodsList(ctx context.Context, req *proto.GoodsFilterRequest) (*proto.GoodsListResponse, error) {
	goodsListResponse := &proto.GoodsListResponse{}
	var goods []model.Goods
	localDB := global.Db.Model(model.Goods{})

	q := elastic.NewBoolQuery()
	req.Keywords = "四川攀枝花"
	if req.Keywords != "" {
		//localDB = localDB.Where("name LIKE ?", "%"+req.Keywords+"%")
		q = q.Must(elastic.NewMultiMatchQuery(req.Keywords, "name", "goods_brief"))
	}
	if req.IsHost {
		q = q.Filter(elastic.NewTermQuery("is_host", req.IsHost))
	}
	if req.IsNew {
		//localDB = localDB.Where(model.Goods{IsNew: true})
		q = q.Filter(elastic.NewTermQuery("is_new", req.IsNew))
	}
	if req.PriceMin > 0 {
		//localDB = localDB.Where("shop_price>=?", req.PriceMin)
		q = q.Filter(elastic.NewRangeQuery("shop_price").Gte(req.PriceMin))
	}
	if req.PriceMax > 0 {
		//localDB = localDB.Where("shop_price<=?", req.PriceMax)
		q = q.Filter(elastic.NewRangeQuery("shop_price").Lte(req.PriceMin))
	}
	if req.BrandId > 0 {
		//localDB = localDB.Where("brand_id=?", req.BrandId)
		q = q.Filter(elastic.NewTermQuery("brand_id", req.BrandId))
	}

	//通过category查询商品
	var subQuery string
	categoryIds := make([]interface{}, 0)
	if req.TopCategory > 0 {
		var category model.Category
		if resutl := global.Db.First(&category, req.TopCategory); resutl.RowsAffected == 0 {
			return nil, status.Errorf(codes.NotFound, "商品分类不存在")
		}
		if category.Level == 1 {
			subQuery = fmt.Sprintf("select id from category where parent_category_id in (select id from category where parent_category_id = %d)", req.TopCategory)
		} else if category.Level == 2 {
			subQuery = fmt.Sprintf("select id from category where parent_category_id = %d", req.TopCategory)
		} else if category.Level == 3 {
			subQuery = fmt.Sprintf("select id from category where id = %d", req.TopCategory)
		}
		localDB = localDB.Where(fmt.Sprintf("category_id in (%s)", subQuery))

		type Result struct {
			ID int32
		}
		var results []Result
		global.Db.Model(model.Category{}).Raw(subQuery).Scan(&results)
		for _, v := range results {
			categoryIds = append(categoryIds, v.ID)
		}
		q = q.Filter(elastic.NewTermsQuery("category_id", categoryIds...))
	}
	if req.Page <= 0 {
		req.Page = 1
	}
	switch {
	case req.Page > 100:
		req.Page = 100
	case req.PagePerNums <= 0:
		req.PagePerNums = 10
	}
	res, err := global.EsClient.Search().Index("es-goods").Query(q).From(int(req.Page)).Size(int(req.PagePerNums)).Do(context.Background())
	if err != nil {

	}

	goodsListResponse.Total = int32(res.Hits.TotalHits.Value)

	goodsIds := make([]int32, 0)
	for _, v := range res.Hits.Hits {
		goods := model.EsGoods{}
		json.Unmarshal(v.Source, &goods)
		goodsIds = append(goodsIds, goods.ID)
	}

	fmt.Println(goodsIds)
	result := localDB.Preload("Category").Preload("Brands").Find(&goods, goodsIds)
	if result.Error != nil {
		return nil, result.Error
	}

	for _, good := range goods {
		goodsInfoResponse := GoodsModelToResponse(good)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfoResponse)
	}
	return goodsListResponse, nil
}

func (g *GoodsService) BatchGetGoods(ctx context.Context, req *proto.BatchGoodsIdInfoRequest) (*proto.GoodsListResponse, error) {
	return &proto.GoodsListResponse{}, nil
}
func (g *GoodsService) DeleteGoods(ctx context.Context, req *proto.DeleteGoodsIdInfoRequest) (*emptypb.Empty, error) {
	return &emptypb.Empty{}, nil
}
func (g *GoodsService) UpdateGoods(ctx context.Context, req *proto.CreateGoodsInfoRequest) (*emptypb.Empty, error) {
	return &emptypb.Empty{}, nil
}
func (g *GoodsService) GetGoodsDetial(ctx context.Context, req *proto.GoodsInfoRequest) (*proto.GoodsInfoResponse, error) {

	var good model.Goods
	if res := global.Db.First(&good, req.Id); res.RowsAffected == 0 {
		status.Errorf(codes.NotFound, "商品信息不存在")
	}
	goodsInfoResponse := GoodsModelToResponse(good)

	return &goodsInfoResponse, nil
}
